import { initFullLayer, removeFullLayer } from '../../utils/LayerUtil';

/**
 * 渲染组件
 */
class Renderer {
  constructor(tool, option) {
    this.tool = tool;
    this.layeridPrefix = 'Renderer';
    Object.assign(this, option);
    this.events = {
      click: () => {},
      mouseover: () => {},
      mousedown: () => {},
      dblclick: () => {}
    };
    this._eventhandle = this.eventhandle.bind(this);
    this.initial();
  }

  /**
   * 获取地图对象
   */
  getMap() {
    return this.tool.getMap();
  }

  /**
   * 初始化渲染组件
   */
  initial() {
    initFullLayer(this);
    this.addEvents();
  }

  /**
   * 加载渲染数据
   * @param {features} features 图形数据
   */
  setData(features) {
    this.getMap().getSource(this._sourceId).setData(turf.featureCollection(features));
  }

  getData() {
    return this.getMap().getSource(this._sourceId).serialize().data;
  }

  /**
   * 清除渲染数据
   */
  clear() {
    this.setData([]);
  }

  /**
   * 删除渲染组件
   */
  remove() {
    removeFullLayer(this);
    this.removeEvents();
  }

  /**
   * 样式设置
   * @param {Object} styles 式样
   * @example
   * {
   *     layout: {
   *         key: value,
   *         key: value
   *     },
   *     paint: {
   *         key: value,
   *         key: value
   *     }
   * }
   */
  setStyle(style) {
    if(style.polygon) {
      this.setPolygonStyle(style.polygon);
    }
    if(style.linestring) {
      this.setLineStringStyle(style.linestring);
    }
    if(style.point) {
      this.setPointStyle(style.point);
    }
    if(style.marker) {
      this.setMarkerStyle(style.marker);
    }
  }

  /**
   * 设置多边形式样
   * @param {*} styles 式样
   */
  setPolygonStyle(styles) {
    this.setLayerStyle(this._layerPolygonId, styles);
  }

  /**
   * 设置线式样
   * @param {*} styles 式样
   * @ignore
   */
  setLineStringStyle(styles) {
    this.setLayerStyle(this._layerLinestringId, styles);
  }

  /**
   * 设置点式样
   * @param {*} styles 式样
   * @ignore
   */
  setPointStyle(styles) {
    this.setLayerStyle(this._layerPointId, styles);
  }

  /**
   * 设置标记式样
   * @param {*} styles 式样
   * @ignore
   */
  setMarkerStyle(styles) {
    this.setLayerStyle(this._layerMarkerId, styles);
  }

  /**
   * 设置图层式样
   * @param {*} layerid 图层Id
   * @param {*} styles 式样
   * @ignore
   */
  setLayerStyle(layerid, styles) {
    if (styles.layout) {
      this.setLayoutProperty(layerid, styles.layout);
    }
    if (styles.paint) {
      this.setPaintProperty(layerid, styles.paint);
    }
  }

  /**
   * 设置图层的布局属性
   * @param {*} layerid 图层Id
   * @param {*} layout 布局属性
   * @ignore
   */
  setLayoutProperty(layerid, layout) {
    for (var key in layout) {
      this.getMap().setLayoutProperty(layerid, key, layout[key]);
    }
  }

  /**
   * 设置图层的绘制属性
   * @param {*} layerid 图层Id
   * @param {*} paint 绘制属性
   * @ignore
   */
  setPaintProperty(layerid, paint) {
    for (var key in paint) {
      this.getMap().setPaintProperty(layerid, key, paint[key]);
    }
  }

  /**
   * 图层绑定事件
   * @ignore
   */
  addEvents() {
    Object.keys(this.events).forEach((eventName) => {
      this.getMap().on(eventName, this._eventhandle);
    });
  }

  /**
   * 图层触发事件
   * @param {*} e 事件参数
   * @ignore
   */
  eventhandle(e) {
    var eventName = e.type;
    if(this.events[eventName]) {
      this.events[eventName](this.queryUnderFeatures(e));
    }
  }

  /**
   * 图层移除事件
   * @ignore
   */
  removeEvents() {
    Object.keys(this.events).forEach((eventName) => {
      this.getMap().off(eventName, this._eventhandle);
    });
  }

  /**
   * 设置图层事件
   * @param {Object} events 事件
   */
  setEvents(option) {
    if(option.click) {
      this.events.click = option.click;
    }
    if(option.mouseover) {
      this.events.mouseover = option.mouseover;
    }
    if(option.mousedown) {
      this.events.mousedown = option.mousedown;
    }
    if(option.dblclick) {
      this.events.dblclick = option.dblclick;
    }
  }

  /**
   * 查询可见图层中，与查询条件匹配的要素数组
   * @param {*} e 查询条件
   * @ignore
   */
  queryUnderFeatures(e) {
    var features = this.getMap().queryRenderedFeatures(e.point, { layers: this._layerIds });
    return features;
  }
}

export default Renderer;
